﻿using System;
using System.Linq;
using System.Timers;
using Emotiv;
using Mipic.Infrastructure.Services;

namespace Mipic.Modules.Epoc.Services
{
    public class EpocService : IEpocService
    {
        
        #region //--------- Private Fields --------------//
        
        private readonly EmoEngine _engine = EmoEngine.Instance;
        private readonly Timer _timer;

        private double _frustration;
        private double _engagement;
        private double _excitement;

        #endregion
        
        #region //--------- Public Constructors ---------//
        
        public EpocService()
        {
            _engine.AffectivEmoStateUpdated += OnAffectiveEmoStateUpdated;
            _engine.Connect();
            
            _timer = new Timer(1000);
            _timer.Elapsed += OnTimerElapsed;
        }
        
        void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            _engine.ProcessEvents(1000);
        }
        
        #endregion
        
        #region //--------- Interface Members -----------//
        
        /// <summary>
        /// Occurs when Epoc is updated.
        /// </summary>
        public event EventHandler Updated;
        
        /// <summary>
        /// Gets the frustration.
        /// </summary>
        /// <returns></returns>
        public double GetFrustration()
        {
            return _frustration;
        }
        
        /// <summary>
        /// Gets the engagement.
        /// </summary>
        /// <returns></returns>
        public double GetEngagement()
        {
            return _engagement;
        }

        /// <summary>
        /// Gets the excitement.
        /// </summary>
        /// <returns></returns>
        public double GetExcitement()
        {
            return _excitement;
        }
        
        /// <summary>
        /// Starts receiving data.
        /// </summary>
        public void Start()
        {
            _timer.Start();
        }
        
        /// <summary>
        /// Stops receiving data.
        /// </summary>
        public void Stop()
        {
            _timer.Stop();
        }

        #endregion
        
        #region //--------- Event Handlers --------------//
        
        /// <summary>
        /// Called when affective emo state updated.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="Emotiv.EmoStateUpdatedEventArgs" /> instance containing the event data.</param>
        private void OnAffectiveEmoStateUpdated(object sender, EmoStateUpdatedEventArgs args)
        {
            _frustration = args.emoState.AffectivGetFrustrationScore();
            _engagement = args.emoState.AffectivGetEngagementBoredomScore();
            _excitement = args.emoState.AffectivGetExcitementShortTermScore();
            
            if (Updated != null)
            {
                Updated(this, EventArgs.Empty);
            }
        }

        #endregion

    }
}